﻿using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 异步编程
{
    public class AsyncClass
    {

        /**
          什么是异步编程？
              同步、异步主要是用来修饰方法的。
              ★、同步方法：  调用这需要等待该方法执行完毕并返回才能继续执行，成为“同步方法”
              ★、异步方法：  当一个方法被调用时立即返回，并获取一个线程执行该方法的内部业务，调用者不用等待该方法执行完毕，称为“异步方法”
                              （异步方法的好处在于非阻塞，（调用线程（主线程）不用暂停等待子线程完成），因此我们把不需要立即使用结果、较为耗时
                                  的任务设置为异步执行，可以提高主线程的运行效率。）
       */

        /**
              Task 类
                    (   
                        Task 从字面理解就是一个"任务"，而这个任务的本质是单开一个线程、独立的去执行一些操作，相对于主线程是独立的，称为"异步任务"，
                             所以，从这个意义上讲，如果一个方法返回类型为Task类，就是说该方法返回一个异步执行的任务，那么这个方法就是"异步方法"

                             eg: public async Task<WorkflowOutput> GetVerifyViewAsync()
                     )
                    Task类表示一个不返回值且通常异步执行的单个操作。
                    (对于要返回值的异步操作，要使用 Task<TResult>类)
                    由于对象执行Task任务的工作通常以异步的方式在线程池线程上执行，而不是在主应用程序线程上同步执行，
                    因此，可以使用Status属性，以及IsCanceled、IsCompleted 和IsFaulted 属性来确定任务的状态。
                    通常使用Lamda表达式来指定Task要执行的工作。
         * */

        /**
                进程、线程、任务  三者关系：
                   ①、 进程： 通常被定义为一个程序的执行。可以把进程看作是一个独立的程序，在内存中拥有独立的数据空间和代码空间。一个进程拥有的数据和变量只属于它自己。
                   ②、 线程 Thread： 线程则是某一进程中单独运行的一个执行流。也就是说线程存在与进程之中。 （一个进程由多个线程构成，线程之间共享进程的数据和代码）
                   ③、 任务Task :   任务的概念是抽象的，指由软件完成的一个活动。一个任务可以是一个进程，也可以是一个线程。简而言之，任务就是一系列共同为了完成一个目标的操作。
         **/



        // 创建Task的三种方式
        [Test]
        public void TaskTest()
        {
            //1、创建Task 但不会执行(用的很少)
            Task task1 = new Task(() => {                   //这里只是声明了个task，并没有执行
                Thread.Sleep(2000);//线程休眠2秒
                
            });
            task1.Start();
            Thread.Sleep(2000);
        }

        /// <summary>
        /// 第二种创建方式（自动执行）
        /// </summary>
        [Test]
        public void CreateTask2()
        {
            //2、创建任务，并自动执行
            var task2 = Task.Factory.StartNew(() => { 
                Console.WriteLine("这是task2");
            });
            Thread.Sleep(200);
        }


        /// <summary>
        /// 创建任务，并给任务传递参数
        /// </summary>
        [Test]
        public void CreateTask2WithParams()
        {
            //2、创建任务，并自动执行
            var task2 = Task.Factory.StartNew(x => {
                Console.WriteLine($"这是task2,参数为："+x);
            },30);          //30是传递给Task的参数，如果有多个参数，可以直接封装成对象，将对象传递给Task
            Thread.Sleep(200);
        }


        /// <summary>
        /// 
        /// </summary>
        [Test]
        public void CreateTask3() {
            //3、第三中创建方式，可直接进行，可以有返回值
            Task task3 = Task.Run(() => {
                Console.WriteLine("这是task3");
            });
            Thread.Sleep(200);
        }



        [Test]
        public void CreateTask3WithReturn()
        {
            //3、第三中创建方式，可直接进行，可以有返回值
            Task<int> task3 = Task.Run<int>(() => {   //Run后面的<int>可以不用写，但是你要知道是在Run后面定义返回值的类型参数
                Console.WriteLine("这是task3");
                return 300;
            });
            //获取task3的返回值
            Console.WriteLine("task3返回值："+task3.Result);//task3.Result会等到task3任务执行完毕
        }



        //任务等待执行的四种方式
        [Test]
        public void TestTaskWait()
        {
            Task task1 = Task.Run(() =>
            {
                Console.WriteLine("任务1");
            });
            task1.Wait();//等待task1任务执行完毕

            Task task2 = Task.Run(() =>
            {
                Console.WriteLine("任务2");
            });
            task2.Wait();

            Task task3 = Task.Run(() =>
            {
                Console.WriteLine("任务3");
            });
            task3.Wait();

            Task task4 = Task.Run(() =>
            {
                Console.WriteLine("任务4");
            });
            task4.Wait();

            Console.WriteLine("所有任务执行完毕");
           

            //由输出结果可见，任务的执行顺序是随机的，不是说先定义就先执行的。
        }
    }
}
